﻿namespace Example.Creational.ObjectPool
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public sealed class CarPool
    {
        private static readonly CarPool _pool = new CarPool();

        private CarPool()
        {
            Cars = new Dictionary<Car, WeakReference>();
        }

        public static int Availability
        {
            get
            {
                int value;

                lock (_pool)
                {
                    value = _pool.Cars.Where(x => null == x.Value || !x.Value.IsAlive).Count();
                }

                return value;
            }
        }

        private Dictionary<Car, WeakReference> Cars { get; set; }

        public static void Add(params Car[] cars)
        {
            foreach (var car in cars)
            {
                lock (_pool)
                {
                    _pool.Add(car);
                }
            }
        }

        public static Car Get()
        {
            Car result = null;

            if (0 < Availability)
            {
                lock (_pool)
                {
                    var item = _pool.Cars.Where(x => null == x.Value || !x.Value.IsAlive).FirstOrDefault();

                    var value = new WeakReference(item.Key);
                    _pool.Cars[item.Key] = value;

                    result = (Car)value.Target;
                }
            }

            return result;
        }

        public static void Return(Car car)
        {
            if (null == car)
            {
                throw new ArgumentNullException("car");
            }

            lock (_pool)
            {
                _pool.Cars[car] = null;
            }
        }

        private void Add(Car car)
        {
            Cars.Add(car, new WeakReference(null));
        }
    }
}